﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Xml.Serialization;
using RG.Common;
using Microsoft.Practices.Unity;

namespace RG.Common
{
    public interface IUserSettings
    {
        FrameDesc UserFrames();
    }

    [XmlInclude(typeof(FrameGroup))]
    [XmlInclude(typeof(FrameSingle))]
    [XmlInclude(typeof(NoGrantFrameSingle))]
    [XmlInclude(typeof(SingleTabFrame))]
    public abstract class FrameDesc
    {
        public string Name { get; set; }
        public string Hint { get; set; }
        public string HyperlinkUrl { get; set; }
        public string HyperlinkText { get; set; }
    }
    [SupportDataBinding]
    public class FrameGroup : FrameDesc
    {
        protected readonly List<FrameDesc> childs = new List<FrameDesc>();
        public List<FrameDesc> Childs { get { return childs; } }
    }


    public class FrameSingle : FrameDesc
    {
        public string TypeName { get; set; }
        public string AssemblyName { get; set; }

        protected Type type;
        public Type Type
        {
            get
            {
                if (type == null)
                {
                    var asm = Assembly.Load(AssemblyName);
                    type = asm.GetType(TypeName);
                    if (type == null)
                        throw new ApplicationException(TypeName);
                }
                return type;
            }
        }
    }

    public class NoGrantFrameSingle : FrameSingle
    { }

    public class SingleTabFrame : FrameSingle
    { }

    public class FileUserSettings : IUserSettings
    {
        [Dependency("FramesConfigFile")]
        public string FramesConfigFile { get; set; }

        protected virtual FrameGroup CheckAccess(FrameGroup frames)
        {
            return frames;
        }

        private FrameGroup root;
        public FrameDesc UserFrames()
        {
            if (root == null)
            {
                using (Stream file = File.Open(FramesConfigFile, FileMode.Open))
                {
                    root = UserFramesFromStream(file);
                    file.Close();
                }
            }
            return root;
        }

        public FrameGroup UserFramesFromStream(Stream from)
        {
            var mySerializer = new XmlSerializer(typeof(FrameDesc));
            var all = (FrameGroup)mySerializer.Deserialize(from);
            return CheckAccess(all);
        }
    }
    public class RestrictedFileUserSettings : FileUserSettings
    {
        private FrameDesc CheckFrameSingle(FrameSingle frame)
        {
            return frame;
        }

        private FrameGroup CheckFrameGroup(FrameGroup parent)
        {
            var group = new FrameGroup
            {
                Name = parent.Name,
                Hint = parent.Hint,
                HyperlinkText = parent.HyperlinkText,
                HyperlinkUrl = parent.HyperlinkUrl
            };

            foreach (var child in parent.Childs)
            {
                var check = CheckFrameDesc(child);
                if (check != null)
                    group.Childs.Add(check);
            }
            return group.Childs.Count == 0 ? null : group;
        }

        private FrameDesc CheckFrameDesc(FrameDesc child)
        {
            if (child is FrameSingle)
                return CheckFrameSingle((FrameSingle)child);
            if (child is FrameGroup)
                return CheckFrameGroup((FrameGroup)child);
            return null;
        }

        protected override FrameGroup CheckAccess(FrameGroup frames)
        {
            return frames;
        }
    }

   
}
